<?php

namespace app\msgapi\service;

use app\utils\Arr;
use app\utils\Str;
use app\msgapi\model\{Cust, Department, HuihuaGroup, HuihuaTables, User, UserCust};
use think\facade\{Cache, Db, Log};
error_reporting(E_ERROR | E_PARSE);
class HsorganizationService
{

    /**获取指定部门成员(带聊天\客户统计信息)列表
     * @param $data
     * @param $admin_groupid
     * @param $adminid
     * @return \think\response\Json
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function getDeparmentMembersChatCustLst($data,$admin_groupid,$adminid)
    {
        $userlst = $this->getDeparmentMembers($data,$admin_groupid,$adminid,true);
        return $this->getStaffLst($data,true,$userlst);
    }

    /**获取所有企业成员
     * @return \think\response\Json
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function getAllUser()
    {
        $alluser = User::field('userid,name')->select()->toArray();
        return success_json('成功',$alluser);
    }

    /**根据userid获取成员或者客户信息(名片消息用)
     * @param $data
     * @return \think\response\Json
     */
    public function getUserOrCustInfo($data)
    {
        if(!$data['userid']) return error_json('参数错误');
        $userinfo = User::where('userid','=',$data['userid'])->field('name,avatar')->findOrEmpty()->toArray();
        if($userinfo) return success_json('成功',$userinfo);
        $custinfo = Cust::where('external_userid','=',$data['userid'])->field('name,avatar')->findOrEmpty()->toArray();
        if($custinfo) return success_json('成功',$custinfo);
        return error_json('资源不存在');
    }

    /**员工统计列表
     * @param false $is_inside 是否内部调用
     * @param array $userlst    内部调用成员userid列表
     * @return \think\response\Json
     */
    public function getStaffLst($data,$is_inside = false , $userlst = []){
        $limit = $data['limit']?:config('page.defaule_limit');
        if($data['name']){
            $where[] = ['user.name','like',"%{$data['name']}%"];
        }
        if($data['start_time'] && $data['end_time']){
            $start_time = trim($data['start_time']); $end_time = trim($data['end_time']);
            $wherecust = " AND cust.createtime between ".strtotime($start_time).' AND '.strtotime($end_time) ;
        }elseif (!$data['start_time'] && $data['end_time']){
            $end_time = trim($data['end_time']);
            $wherecust = " AND cust.createtime <= " . strtotime($end_time) ;
        }elseif($data['start_time'] && !$data['end_time']){
            $start_time = trim($data['start_time']);
            $wherecust = " AND cust.createtime >= " . strtotime($start_time) ;
        }
        if($is_inside) $where[] = ['userid','in',$userlst]; //内部调用
        //有权限的所有成员
        $auth_user_arr = HsorganizationService::getDepartmentLst(2,0,request()->admin_groupid,request()->adminid);
        if(!$is_inside){ //员工统计用
            if(($auth_user_arr !== 'all') && empty($auth_user_arr)) return error_json('暂无成员权限');
            if(($auth_user_arr !== 'all') && !empty($auth_user_arr) ) $where[] = ['userid','in',$auth_user_arr];//成员权限
        }
        $cust_list = User::alias('user')
            ->field('user.userid,count(cust.uid) as count')
            ->join('user_cust cust','user.id = cust.uid' . $wherecust,'left')
            ->group('user.userid')
            ->where($where)
            ->paginate($limit)->toArray();

        $cust_list = array_column($cust_list['data'],'count','userid');
        $huihua_tables = HuihuaTables::order('id desc')->select()->toArray();
        if(!$huihua_tables) return error_json('记录表查询为空');
        if($huihua_tables){
            $first_table_suffix = $huihua_tables[0]['table_suffix'];
            $firstwhere = [];
            if($data['name']) $firstwhere[] = ["user0.name","like","%{$data['name']}%"];
            if($is_inside) $firstwhere[] = ["user0.userid","in",$userlst]; //内部调用
            if(!$is_inside && ($auth_user_arr !== 'all') ) $firstwhere[] = ["user0.userid","in",$auth_user_arr]; //员工统计用,成员权限
            if($data['start_time'] && $data['end_time']){
                $start_time = trim($data['start_time']); $end_time = trim($data['end_time']);
                $first_wheremsg = " AND msg_$first_table_suffix.msgtime between '$start_time' AND '$end_time'";
            }elseif (!$data['start_time'] && $data['end_time']){
                $end_time = trim($data['end_time']);
                $first_wheremsg = " AND msg_$first_table_suffix.msgtime <= '$end_time'";
            }elseif($data['start_time'] && !$data['end_time']){
                $start_time = trim($data['start_time']);
                $first_wheremsg = " AND msg_$first_table_suffix.msgtime >= '$start_time'";
            }
            $firstsql = User::alias("user0")
                ->field( "user0.name,user0.avatar,user0.gender,user0.userid,user0.ispermit,user0.status,msg_$first_table_suffix.fromid")
                ->join("hs_huihua_msg_$first_table_suffix msg_$first_table_suffix","msg_$first_table_suffix.fromid = user0.userid".$first_wheremsg,'left')
                ->where($firstwhere);
            foreach ($huihua_tables as $k => $tables)
            {
                if($k == 0) continue; //跳过第一个表
                $where = [];
                if($data['name']) $where[] = ["user$k.name","like","%{$data['name']}%"];
                if($is_inside) $where[] = ["user$k.userid","in",$userlst]; //内部调用
                if(!$is_inside && ($auth_user_arr !== 'all') ) $where[] = ["user$k.userid","in",$auth_user_arr]; //员工统计用,成员权限
                if($data['start_time'] && $data['end_time']){
                    $start_time = trim($data['start_time']); $end_time = trim($data['end_time']);
                    $first_wheremsg = " AND msg_{$tables['table_suffix']}.msgtime between '$start_time' AND '$end_time'";
                }elseif (!$data['start_time'] && $data['end_time']){
                    $end_time = trim($data['end_time']);
                    $first_wheremsg = " AND msg_{$tables['table_suffix']}.msgtime <= '$end_time'";
                }elseif($data['start_time'] && !$data['end_time']){
                    $start_time = trim($data['start_time']);
                    $first_wheremsg = " AND msg_{$tables['table_suffix']}.msgtime >= '$start_time'";
                }
                $sql = User::alias("user$k")
                    ->field( "user$k.name,user$k.avatar,user$k.gender,user$k.userid,user$k.ispermit,user$k.status,msg_{$tables['table_suffix']}.fromid")
                    ->join("hs_huihua_msg_{$tables['table_suffix']} msg_{$tables['table_suffix']}","msg_{$tables['table_suffix']}.fromid = user$k.userid".$first_wheremsg,'left')
                    ->where($where)->buildSql();
                $firstsql = $firstsql->unionAll($sql);
            }
            $firstsql = $firstsql->buildSql();
            $list = Db::table($firstsql . 'as user')->field('*,count(fromid) as count')
                ->group('user.userid')
                ->paginate($limit)->each(function ($item)use($cust_list){
                    $item['cust_count'] = $cust_list[$item['userid']];
                    return $item;
                })->toArray();
        }
        return success_json('成功',$list);
    }

    /**侧边栏获取客户会话对象列表(用客户id获取成员列表,带授权权限)
     * @param $data array
     * @param $admin_groupid int|string
     * @param $adminid int|string
     * @return \think\response\Json
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function getCustMessageObj(array $data,$admin_groupid,$adminid)
    {
        if(!$data['external_userid']) return error_json('参数错误');
        $auth_user_arr = self::getDepartmentLst(2,1,$admin_groupid,$adminid); //默认仅获取监管成员权限
        if(empty($auth_user_arr)) return error_json('暂未获得监管授权');
        $limit = $data['limit']?:config('page.defaule_limit');
        if(!$data['is_crowd'] || $data['is_crowd'] == 0){
            $where = [];$whereor = [];
            $data['searchname'] && $where[] = ['name', 'like', "%{$data['searchname']}%"];
            if($auth_user_arr !== 'all') $where[] = ['userid','in',$auth_user_arr];
            $userId = User::where($where)->column('userid');
            foreach ($userId as $value) {
                $whereor[] = "FIND_IN_SET('{$value}',`userlist`)";
                $whereor[] = "FIND_IN_SET('{$value}',`userlist`)";
            }
            if ($whereor) $whereor = implode(' OR ', $whereor);
            $list = HuihuaGroup::where("FIND_IN_SET('{$data['external_userid']}',`userlist`)")
                ->where('is_crowd','=',0)
                ->where($whereor)
                ->withAttr('userlist', function ($item) use ($data) {
                    $ulist = explode(',', $item);
                    if ($ulist[0] == $data['external_userid']) return $ulist[1];
                    return $ulist[0];
                })->paginate($limit)->each(function ($item){
                    $item['userInfo'] = User::field('name,avatar')->where('userid','=',$item['userlist'])->findOrEmpty()->toArray();
                    return $item;
                })->toArray();
            return success_json('成功',$list);
        }else{
            $list = HuihuaGroup::field('group.*,group_chat.name,group_chat.type as group_type')
                ->alias('group')
                ->join('group_chat group_chat', 'group_chat.chat_id = group.chatid', 'left');
            $data['searchname'] && $list = $list->where('group_chat.name', 'like', "%{$data['searchname']}%");
            $list = $list->where('is_crowd', '=',1)
                ->where("FIND_IN_SET('{$data['external_userid']}',`userlist`)")
                ->order('group.update_time desc')
                ->paginate($limit)->toArray();
            return success_json('成功',$list);
        }
    }

    /**手动同步组织架构\通讯录
     * @param $data
     * @return \think\response\Json
     */
    public function syncContacts($data)
    {
        $is_ok = $data['is_ok']; //确认是否执行完成,默认第二次请求开始传参
        HsoperateLogService::addLog(3, request()->adminid,'手动同步了通讯录','');
        if(Cache::get('is_synuser') !== true || !Cache::get('is_synuser')){
            if($is_ok == 'true'){ return success_json('同步已完成'); }
            exec('php '.app()->getRootPath().'\think synuser', $a, $b);
            return success_json('程序已开始执行');
        }else{
            Log::write('同步程序已在执行中,请等待执行完成.','error');
            return error_json('同步程序已在执行中,请等待执行完成');
        }
    }

    /**全量获取部门\成员信息或仅成员(带授权范围权限)
     * @param int $getuser 是否获取成员 0否 1是 2仅获取成员
     * @param int $ispermit 是否仅获取监管成员 1是 0否
     * @param $admin_groupid
     * @param $adminid
     * @return \think\response\Json
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function getDepartmentLst($getuser,$ispermit,$admin_groupid,$adminid)
    {
        $range = HsadminService::getAdminRange($admin_groupid,$adminid);
        $has_auth_departments = $range['deparment_lst'] ? explode(',',$range['deparment_lst']) : [];
        $departmentLst = Department::field('*,if(1,1,0) as is_auth')->order('order asc')->select()->toArray();
        //获取拥有权限的所有部门,包括子部门.$range 等于all拥有所有权限
        //创建一个保存最后输出结果的数据
        $auth_departments = [];
        if($range !== 'all'){
            foreach (array_values($has_auth_departments) as $k => $v) {
                //找到所有子级部门
                $res = self::getAllAuthDepartments($departmentLst,$v);

                $auth_departments = array_merge($auth_departments,$res);
            }
            $auth_departments = array_unique(array_merge($has_auth_departments,$auth_departments));
        }
        //仅获取成员||手机端侧边栏用
        if($getuser == 2) return self::getOnlyUsers($auth_departments ,$range ,$ispermit);
        return success_json('成功',$this->getDepartmentTree($auth_departments,$range,$departmentLst,$getuser,$ispermit));
    }



    /**全量获取组织架构\成员信息
     * 获取部门树
     * @param array $auth_departments 有权限的部门
     * @param array|string $range 账号权限,all拥有所有权限,其他为部分权限
     * @param array $departmentLst 所有部门列表
     * @param int $getuser 是否获取成员 1是 0否 默认1
     * @return array
     * @throws \Throwable
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    private function getDepartmentTree(array $auth_departments,$range, array $departmentLst,int $getuser = 1,int $ispermit){
        $show_department = [];
        if($getuser) {
            if($range == 'all'){
                if($ispermit > 0)$userList = User::where('ispermit','>',0)->select()->toArray();
                else $userList = User::select()->toArray();
            }else{
                if($ispermit > 0) $userList = User::where('ispermit','>',0)->where('userid', 'in', self::getOnlyUsers($auth_departments, $range, 0))->select()->toArray();
                else $userList = User::where('userid', 'in', self::getOnlyUsers($auth_departments, $range, 0))->select()->toArray();
            }
            //部门
            $departmentLst = array_column($departmentLst, null, 'id');
            foreach ($userList as &$value) {
                $value['is_auth'] = 1;
                foreach (explode(',', $value['department_list']) as $department_id) {
                    $value['now_department'] = $department_id;
                    $departmentLst[$department_id]['user'][] = $value;
                }
            }
            foreach ($departmentLst as $key=>&$val){
                $val['is_auth'] =1;
                if($val['user']){
                    $show_department = array_unique(array_merge($show_department,[(int)$val['id']],$this->getParent($departmentLst,$val)));
                }
            }
        }else{
            $range_depart = explode(',',$range['deparment_lst']);
            foreach ($departmentLst as $key=>&$val){
                $val['is_auth'] =1;
                if(in_array($val['id'],$range_depart)||$range=='all'){
                    $show_department = array_unique(array_merge($show_department,[(int)$val['id']],$this->getParent($departmentLst,$val)));
                }
            }
        }
        foreach ($departmentLst as $key=>$val1){
            if(!in_array($val1['id'],$show_department)){
                unset($departmentLst[$key]);
            }
        }
        return  Arr::arrayToTree($departmentLst,'id','parentid','child');
    }

    /**
     * 递归获取父级部门
     * @param $department
     * @param $d_id
     * @param $result
     * @return array
     */
    public function getParent($department,$d_id,&$result=[]){
        foreach ($department as $value){
            if($value['id'] == $d_id['parentid']){
                $result[] = $value['id'];
                $this->getParent($department,$value,$result);
            }
        }
        return $result;
    }


    /**获取指定部门成员(带授权范围权限)
     * @param $data
     * @param $admin_groupid
     * @param $adminid
     * @param false $is_inside 是否内部调用
     * @return \think\response\Json
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function getDeparmentMembers($data,$admin_groupid,$adminid,$is_inside = false)
    {

        $range = HsadminService::getAdminRange($admin_groupid,$adminid);
        $has_auth_departments = $range['deparment_lst'] ? explode(',',$range['deparment_lst']) : [];
        $limit = $data['limit']?:config('page.defaule_limit');
        $order = 'u.id desc';
        if ($data['order']) {
            $order = 'u.' . $data['order'].' '.($data['sort']?:'desc');
        }
        if(!$data['department_id']) return error_json('参数错误');
        $departmentLst = Department::order('order asc')->select()->toArray();
        //创建一个保存最后输出结果的数据
        $auth_departments = [];
        if($range !== 'all'){
            foreach (array_values($has_auth_departments) as $k => $v) {
                //找到所有子级部门
                $res = self::getAllAuthDepartments($departmentLst,$v);
                $auth_departments = array_merge($auth_departments,$res);
            }
            $auth_departments = array_unique(array_merge($has_auth_departments,$auth_departments));
            if(!empty($auth_departments) && !in_array($data['department_id'],$auth_departments)) return error_json('没有部门权限');
        }
        $member_lst = User::alias('u')
          ->join('department d','u.main_department = d.id','left')
            ->field('u.*,d.name as main_department_name');
        //$range 等于 all 拥有所有权限
        if($range !== 'all'){
            $whereor = "FIND_IN_SET('{$data['department_id']}',`department_list`)";
            if($range['user_lst']) $whereor = "FIND_IN_SET('{$data['department_id']}',`department_list`) OR `u`.`userid` IN ('{$range['user_lst']}')";
            $member_lst = $member_lst->whereOr($whereor);
        }else{
            $member_lst->where("FIND_IN_SET('{$data['department_id']}',`department_list`)");
        }
        //内部调用
        if($is_inside) return $member_lst->column('userid');
        $member_lst = $member_lst->order($order)->paginate($limit)->toArray();

        return success_json('成功',$member_lst);
    }

    /**
     * 获取所有被监管成员(带授权范围权限)
     * @param $data
     * @param $admin_groupid
     * @param $adminid
     * @return \think\response\Json
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function getPermitLst($data,$admin_groupid,$adminid)
    {
        $range = HsadminService::getAdminRange($admin_groupid, $adminid);
        $hasAuthDepartments = $range['deparment_lst'] ? explode(',', $range['deparment_lst']) : [];
        $departmentLst = Department::order('order asc')->select()->toArray();
        //获取拥有权限的所有部门,包括子部门.$range 等于all拥有所有权限
        //创建一个保存最后输出结果的数据
        $authDepartments = [];
        if ($range !== 'all') {
            foreach (array_values($hasAuthDepartments) as $v) {
                //找到所有子级部门
                $res = self::getAllAuthDepartments($departmentLst, $v);
                $authDepartments = array_merge($authDepartments, $res);
            }
            $authDepartments = array_unique(array_merge($hasAuthDepartments, $authDepartments));
            $tmpUser = [];
            if ($authDepartments) {
                foreach ($authDepartments as $au) {
                    $whereor[] = "FIND_IN_SET( {$au},`department_list`)" ;
                }
                $users = User::where(implode(' or ', $whereor))->column('userid');
                $tmpUser = array_merge($authDepartments, $users);
            }
            $range['user_lst'] = array_merge($tmpUser, explode(',', $range['user_lst'])); //合并所有有权限的成员
        }
        $limit = $data['limit']?:config('page.defaule_limit');
        $order = 'id desc';
        if ($data['order']) {
            $order = $data['order'].' '.($data['sort']?:'desc');
        }
        $where[] = ['ispermit','>',0]; //包含历史被监管成员
        if ($range !== 'all') {$where[] = ['userid', 'in', $range['user_lst'] ?: ' '];}
        $data['name'] && $where[] = ["name","like","%{$data['name']}%"];
        $lst = User::where($where)->order($order)->paginate($limit)->toArray();
        return success_json('成功', $lst);
    }

    /**递归获取所有子级部门列表
     * @param array $departmentLst 所有部门
     * @param int|string $pid 有权限的部门(单个)
     * @param $child
     * @return array
     */
    public static function getAllAuthDepartments(array $departmentLst,$pid,&$child=[]){
        foreach ($departmentLst as $val){
            if($val['parentid'] == $pid ){
                $child[] = $val['id'];
                self::getAllAuthDepartments($departmentLst,$val['id'],$child);
            }
        }
        return $child;
    }

    /**启用企业成员
     * @param $data
     * @return \think\response\Json
     * @throws \Exception
     */
    public function enableCorpUser($data)
    {
        if(!$data['userid']) return error_json('参数错误');
        $weWorkCorpSelfService = new WeworkCorpSelfService();
        $user_status = User::where([['userid','=',$data['userid']]])->value('status');
        if($user_status != 2) return error_json('成员账号状态错误,操作失败');
        $tmp_res = $weWorkCorpSelfService->editUser(['userid'=>$data['userid'],'enable'=>1]);
        if($tmp_res && $tmp_res['errcode'] != 0) return error_json('操作失败,原因:'.$tmp_res['errmsg']);
        User::where([['userid','=',$data['userid']]])->update(['status'=>1]);
        return success_json('操作成功');
    }


    /**递归获取所有的子级成员
     * 接口解释:该接口获取所有通讯录数据(部门及成员),但是会在部门和成员上做权限范围标记,前端根据部门或成员的is_auth字段来判断权限范围.
     * @param $alldepartments array() 所有部门
     * @param int $id
     * @param int $start
     * @param int $getuser 是否获取成员
     * @param int $ispermit 是否仅获取被监管成员
     * @param $range  array|string   账号权限,all拥有所有权限,其他为部分权限
     * @param $auth_departments 有权限的部门
     * @return array
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
/**
    public static function getChild( array $alldepartments ,$id=0, $start = 0, $getuser = 1, $ispermit = 0, $range, array $auth_departments)
    {
        //创建一个保存最后输出结果的数据
        $tree = [];
        //循环所有数据找到pid为传入id的数组，也就是找到id的子级们
        foreach ($alldepartments as $key => &$value) {
            //找到了子级
            if ($value['parentid'] == $id) {
                $value['is_auth'] = 0; //部门是否有权限添加的字段
                if(in_array($value['id'],$auth_departments) || ($range === 'all') ) $value['is_auth'] = 1; //有权限的部门,$range 等于all拥有所有权限

                //将数组保存进最后结果
                $tree[$start] = $value;
                //为了减少数据量删掉了自己，因为自己不可能是自己的子级
                unset($alldepartments[$key]);
                //将子级的子级数组保存到子级的child数组里（递归查找）
                $tree[$start]['child'] = array_reverse(self::getChild($alldepartments, $value['id'],0,$getuser,$ispermit,$range,$auth_departments));
                if($tree[$start]['child'][0]['id'] == 9999999){ //离职部门挪到最后
                    $tmp = $tree[$start]['child'][0];
                    unset($tree[$start]['child'][0]);
                    $tree[$start]['child'] = array_values($tree[$start]['child']);
                    array_push($tree[$start]['child'],$tmp);
                    unset($tmp);
                }
                $where = [];
                if($ispermit) $where[] = ['ispermit','>',0]; //仅获取被监管成员
                if($getuser){//获取成员 ,now_department字段前端需要,is_auth字段判断是否有权限
                    //部分权限,$range 等于all拥有所有权限
                    if($range !== 'all'){
                        $tmp_userlst = User::field("*,0 as is_auth,{$value['id']} as now_department")->where("FIND_IN_SET('{$value['id']}',`department_list`)")->where($where)->order('order asc')->select()->toArray();
                        $tmp_arr_user = explode(',',$range['user_lst']);
                        foreach ($tmp_userlst as &$vu)
                        {
                            if(in_array($value['id'],$auth_departments) || in_array($vu['userid'],$tmp_arr_user))
                            {
                                $vu['is_auth'] = 1;
                                //缓存权限范围内的成员,用来限制[接口]聊条记录查询,同时可限制对整个授权范围接口的请求,range为'all'拥有所有权限
                                if(Cache::has('admin' . request()->adminid . '_auth_user_arr') && (!in_array($vu['userid'],Cache::get('admin' . request()->adminid . '_auth_user_arr')))){
                                    Cache::push('admin' . request()->adminid . '_auth_user_arr',$vu['userid']);
                                }else{
                                    Cache::set('admin' . request()->adminid . '_auth_user_arr', [$vu['userid']],86400);
                                }
                            }else{
                                $vu['is_auth'] = 0;
                            }
                        }
                    }elseif ($range === 'all'){
                        //缓存权限范围内的成员,用来限制[接口]聊条记录查询,range为'all'拥有所有权限
                        Cache::remember('admin' . request()->adminid . '_auth_user_arr', 'all',86400);
                        $tmp_userlst = User::field("*,1 as is_auth,{$value['id']} as now_department")->where("FIND_IN_SET('{$value['id']}',`department_list`)")->where($where)->order('order asc')->select()->toArray();
                    }
                    $tree[$start]['user'] = $tmp_userlst;
                }
                ++$start;
            }
        }
        return $tree;
    }
 * */


    /**仅获取成员列表(带授权范围权限)
     * 用来手机端侧边栏获取会话成员列表授权控制,同时可限制对整个授权范围接口的请求,range为'all'拥有所有权限
     * @param array $auth_department 有权限的部门
     * @param array|string $range 账号权限,all拥有所有权限,其他为部分权限
     * @param $ispermit int 是否仅获取被监管成员 1是 0否
     * @return array|string
     * @throws \Throwable
     */
    public static function getOnlyUsers(array $auth_department,$range,$ispermit=0){
        if($range === 'all') return 'all'; $whereOr=[];
        if(!Cache::get('only_users_'.request()->adminid)){
            //读取缓存,避免频繁查询
            if(!empty($auth_department)){
                foreach ($auth_department as $val){
                    $whereOr[] = "FIND_IN_SET({$val},`department_list`)";
                }
            }
            if(!empty($range['user_lst'])){
                $userlist = explode(',',$range['user_lst']);
                $userlist = '"'.implode('","',$userlist).'"';
                $whereOr[] ="(`userid` in ({$userlist}))";// ['user_id','in',$range['user_list']];

            }
            if(isset($whereOr)) $whereOr = implode(' OR ',$whereOr);
            if($ispermit > 0) $where[] = ['ispermit','>',0];
            if(empty($auth_department) && empty($range['user_lst'])){
                $only_users = []; //都为空返回空数据,防止都为空时拥有所有成员权限
                //管理员成员权限范围放缓存,避免频繁查询
                Cache::set('only_users_'.request()->adminid,[],86400);
            }else{
                $only_users = User::where($where)->where($whereOr)->column('userid');
                //管理员成员权限范围放缓存,避免频繁查询
                Cache::set('only_users_'.request()->adminid,$only_users,86400);
            }

        }else{
            $only_users = Cache::get('only_users_'.request()->adminid);
        }
        return $only_users;
    }


    /**
     * 部门同步
     * @return false|int
     * @throws \Exception
     */
    public function synDepartment()
    {
        //获取最新部门列表
        $weworkCorpSelfService = new WeworkCorpSelfService();
        $qw_department_lst = $weworkCorpSelfService->getDepartmentList();
        if (($qw_department_lst['errcode'] != 0) && !empty($qw_department_lst['department'])) {
            Log::write('通讯录数据拉取失败,错误码:' . $qw_department_lst['errcode'] . $qw_department_lst['errmsg'], 'error');
        }
        $departmentModel = new Department();
        foreach ($qw_department_lst['department'] as $v) {
            $save_data[] = [
                'id' => $v['id'],
                'name' => $v['name'],
                'name_en' => isset($v['name_en']) ? $v['name_en'] : null,
                'parentid' => $v['parentid'],
                'department_leader' => $v['department_leader'] ? implode(',',$v['department_leader']) : null,
                'order' => $v['order']
            ];
            Log::write(implode(',',$v['department_leader']),'info');
        }

        $save_data[] = [
            'id' => 9999999,
            'name' => '离职员工',
            'name_en' => 'Resigned employees',
            'parentid' => 1,
            'department_leader' => null,
            'order' => 999999999
        ]; //ID为9999999的离职员工部门

        Db::startTrans();
        try {
            //清空所有部门
            $departmentModel->where('id', '>', 0)->delete();
            //新增所有数据
            $res = $departmentModel->insertAll($save_data);
            Log::write('更新部门数据共:' . $res, 'info');
            Db::commit();
            return $res;
        } catch (\Exception $e) {
            Db::rollback();
            Log::write('更新部门数据失败,原因:' . $e->getMessage() . '数据已回滚', 'error');
            return false;
        }

    }


    /**
     * 成员同步
     * @return bool
     * @throws \Exception
     */
    public function synMember()
    {
        //举例:'a123'账号成员离职后,又加入新的'a123'账号成员或'a123'账号原成员再次加入都视为同一账号,数据库中'a123'(数据库中该字段不能唯一)账号会有离职记录和在职记录多条记录,查询到的聊天记录也一样.
        //账号禁用、退出都不放入离职成员目录，只用真正都删除或者推出后自动被删除才放入离职目录。
        //获取最新成员列表
        $weworkCorpSelfService = new WeworkCorpSelfService();
        $qw_member_lst = $weworkCorpSelfService->getUserListByDepartment($departmentid = 1, $fetch_child = 1);
        if (($qw_member_lst['errcode'] != 0) && !empty($qw_member_lst['userlist'])) {
            Log::write('成员(详细)列表数据拉取失败,错误码:' . $qw_member_lst['errcode'] . $qw_member_lst['errmsg'], 'error');
        }
        $userModel = new User();
        $userLst = $userModel->column('userid', 'id');
        $updateData = [];
        $insertData = [];
        $useridSet = [];

        foreach ($qw_member_lst['userlist'] as $k => $v) {
//            Log::write(json_encode($v,256),'info');
            $useridSet[] = $v['userid'];
            $save_data = [
                'userid' => $v['userid'],
                'name' => $v['name'],
                'department_list' => implode(',', $v['department']),
                'order' => implode(',', $v['order']),
                'position' => $v['position'],
                'mobile' => $v['mobile'],
                'gender' => $v['gender'],
                'email' => $v['email'],
                'is_leader_in_dept' => implode(',', $v['is_leader_in_dept']),
                'avatar' => $v['avatar'],
                'alias' => $v['alias'],
                'status' => $v['status'],
                'main_department' => $v['main_department'],
                'qr_code' => $v['qr_code']
            ];
            //更新
            if ($userLst && (in_array($v['userid'], $userLst))) {
                $save_data['id'] = array_search($v['userid'],$userLst); //返回user表(id)
                $updateData[] = $save_data;
            } else {//插入
                $insertData[] = $save_data;
            }
        }
        $del_tmp = array_diff($userLst, $useridSet);
        $insert_num = $update_num = $destroy_num = 0;
        Db::startTrans();
        try {
            if ($insertData) {
                $insert_num = $userModel->insertAll($insertData);
            }
            if ($updateData) {
                $userModel->saveAll($updateData);
                $update_num = count($updateData);
            }
            if ($del_tmp) {
//                $destroy_num = $userModel->destroy(['userid' => $del_tmp], false);
                $userModel->where('userid','in',$del_tmp)->update(['department_list'=>9999999, 'main_department' => 9999999]); //直接放入离职部门,不用删除

            }
            Db::commit();
            Log::write("更新成员信息成功.新增成员:{$insert_num},更新成员:{$update_num},离职成员:{$destroy_num}", 'info');
            return true;
        } catch (\Exception $e) {
            Db::rollback();
            Log::write('更新部门数据失败,原因:' . $e->getMessage() . '数据已回滚', 'error');
            return false;
        }
    }


    /**
     * 同步客户
     * @return bool
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function synCust()
    {

        //批量同步时同步索引，主要避免重复的数据更新，每次同步时创建新的索引值，本次更新遇到同一客户时已更新过的则跳过
        $synflag = Str::createNonceStr(8) . time();

        $userModel = new User(); $custModel = new Cust(); $userCustModel = new UserCust();
        //获取所有成员
        $memberLst = $userModel->where([['main_department','<>',9999999]])->select()->toArray();
        Db::startTrans();
        try {
            $cust_crnum = 0; //新增客户数量
            $cust_upnum = 0; //更新客户数量
            $user_cust_crnum = 0; //成员客户跟进新增数量
            $user_cust_upnum = 0; //成员客户跟进更新数量
            $weworkCorpSelfService = new WeworkCorpSelfService();
            foreach ($memberLst as $val) {
                $cursor = '';
                $netx = false;
                do {
                    //获取当前客户列表
                    $customers = $weworkCorpSelfService->getCustomerBath($val['userid'], $cursor);
                    if ($customers['errcode'] == 0) {
                        $customerLst = $customers['external_contact_list'];
                        foreach ($customerLst as $cval) {
                            $customerInfo = $cval['external_contact'];//客户的基本信息
                            $followInfo = $cval['follow_info']; //企业成员客户跟进信息
                            //查询当前客户信息是否存在，存在则更新，不存在则新增
                            $externalDbInfo = $custModel->where('external_userid', $customerInfo['external_userid'])->findOrEmpty()->toArray();
                            //根据synflag判断当前客户是否已经在本次同步任务中更新，已更新则忽略本次更新操作进入下一步，可略微减少数据库IO
                            $baseData = [
                                'external_userid' => $customerInfo['external_userid'],
                                'name' => isset($customerInfo['name']) ? $customerInfo['name'] : null,
                                'position' => isset($customerInfo['position']) ? $customerInfo['position'] : null,
                                'avatar' => isset($customerInfo['avatar']) ? $customerInfo['avatar'] : null,
                                'corp_name' => isset($customerInfo['corp_name']) ? $customerInfo['corp_name'] : null,
                                'corp_full_name' => isset($customerInfo['corp_full_name']) ? $customerInfo['corp_full_name'] : null,
                                'type' => isset($customerInfo['type']) ? $customerInfo['type'] : 1,
                                'gender' => isset($customerInfo['gender']) ? $customerInfo['gender'] : 0,
                                'unionid' => isset($customerInfo['unionid']) ? $customerInfo['unionid'] : null,
                                'external_profile' => isset($customerInfo['external_profile']) ? json_encode($customerInfo['external_profile']) : null,
                                'synflag' => $synflag,
                            ];

                            if ($externalDbInfo && ($externalDbInfo['synflag'] != $synflag)) {
                                $custModel->update($baseData, ['id' => $externalDbInfo['id']]);
                                $baseid = $externalDbInfo['id'];
                                ++$cust_upnum;
                            } elseif ($externalDbInfo && ($externalDbInfo['synflag'] == $synflag)){
                                $baseid = $externalDbInfo['id'];
                            }else {
                                $info = $custModel->create($baseData);
                                $baseid = $info['id'];
                                ++$cust_crnum;
                            }

                            //处理user_cust表
                            if ($baseid) {
                                $userCustDbInfo = $userCustModel->where('uid', $val['id'])->where('external_uid', $baseid)->findOrEmpty()->toArray();
                                $userData = [
                                    'uid' => $val['id'],
                                    'external_uid' => $baseid,
                                    'remark' => isset($followInfo['remark']) ? $followInfo['remark'] : null,
                                    'description' => isset($followInfo['description']) ? $followInfo['description'] : null,
                                    'createtime' => isset($followInfo['createtime']) ? $followInfo['createtime'] : null,
                                    'tagids' => isset($followInfo['tag_id']) ? json_encode($followInfo['tag_id']) : null,
                                    'remark_corp_name' => isset($followInfo['remark_corp_name']) ? $followInfo['remark_corp_name'] : null,
                                    'remark_mobiles' => isset($followInfo['remark_mobiles']) ? json_encode($followInfo['remark_mobiles'], 256) : null,
                                    'add_way' => isset($followInfo['add_way']) ? $followInfo['add_way'] : 0,
                                    'oper_userid' => isset($followInfo['oper_userid']) ? $followInfo['oper_userid'] : null,
                                    'state' => isset($followInfo['state']) ? $followInfo['state'] : null,
                                ];
                                if ($userCustDbInfo) {
                                    $userCustModel->update($userData, ['id' => $userCustDbInfo['id']]);
                                    ++$user_cust_upnum;
                                } else {
                                    $userCustModel->create($userData);
                                    ++$user_cust_crnum;
                                }
                            }
                        }
                        $netx = $cursor = $customers['next_cursor'];
                    } else {
                        $netx = '';
                        Log::write("成员的客户列表获取失败.失败原因:errcode:{$customers['errcode']},errmsg:{$customers['errmsg']}", 'warning');
                    }

                } while ($netx != '');
            }
            Db::commit();
            Log::write("客户同步成功.新增客户数量:{$cust_crnum},更新客户数量:{$cust_upnum},成员客户跟进新增数量:{$user_cust_crnum},成员客户跟进更新数量:{$user_cust_upnum}", 'info');
            return true;
        } catch (\Exception $e) {
            Db::rollback();
            Log::write('同步客户失败,原因:' . $e->getMessage().$e->getLine() . '数据已回滚', 'error');
            return false;
        }
    }


    /**
     * 同步监管成员
     * @return bool
     * @throws \Exception
     */
    public function synSupervise()
    {
        $weworkCorpSelfService = new WeworkCorpSelfService();
        $permitlist = $weworkCorpSelfService->getPermitUserList();
//        Log::write(json_encode($permitlist,256),'info');
        if($permitlist['errcode'] ==0){
            Db::startTrans();
            try {
                User::where('ispermit','=', 1)->update(['ispermit'=>2]); //先更新所有被监管成员位历史被监管成员
                User::where('userid','in', $permitlist['ids'])->update(['ispermit'=>1]);//再更新目前被监管成员为被监管成员
                Db::commit();
            }catch (\Exception $e){
                Log::write('同步监管成员失败,原因:' . $e->getMessage().$e->getLine() . '数据已回滚', 'error');
                Db::rollback();
            }

            return true;
        }else{
            return false;
        }
    }


    //==================回调用===============

    /**回调新增成员
     * @param $data
     */
    public static function add_user($data)
    {
//        Log::write(json_encode($data),'info');
        $save_data = [
            'userid' => $data['UserID'],
            'name' => $data['Name'],
            'avatar' => $data['Avatar'],
            'status' => $data['Status'],
            'department_list' => $data['Department'],
        ];
        try {
            User::create($save_data);
            Log::write("[回调]创建成员成功",'info');
        }catch (\Exception $e){
            Log::write('[回调]添加成员失败,错误原因:'.$e->getMessage().'行号:'.$e->getLine(),'error');
        }
    }


    /**回调更新成员
     * @param $data
     */
    public static function update_user($data)
    {
        $UserId = $data['UserID'];
        $userModel = new User();
        //用户修改了userid 则将员USERid保留并设置原userid为离职员工中，新增成员为新的userid，删除原userid的部门关联
        //账号禁用、退出都不放入离职成员部门，只用真正删除或者推出后自动被删除才放入离职部门。
        Db::startTrans();
        try {
            if (isset($data['NewUserID'])) {
                $old_userinfo = $userModel->where([['userid','=',$UserId]])->order('id asc')->findOrEmpty()->toArray(); //防止相同的新账号回调后被查到,后面更新错数据
                if($old_userinfo){
                    $change_info = $old_userinfo;
                    unset($change_info['id']);
                    $change_info['userid'] = $data['NewUserID'];
                    $userModel->insert($change_info); //创建新账号
//                    $userModel->destroy(['id' => $old_userinfo['id']], false);  //删除老账号(软删除)
                    $userModel->update(['department_list'=>9999999, 'main_department' => 9999999], ['id' => $old_userinfo['id']]); //直接放入离职部门,不用删除
                }else{
                    $change_info = [
                        'userid' => $data['NewUserID'],
                        'name' => isset($data['Name'])? $data['Name'] : NULL,
                        'avatar' => isset($data['Avatar'])? $data['Avatar'] : NULL,
                        'status' => isset($data['Status'])? $data['Status'] : NULL,
                        'department' => isset($data['Department'])? $data['Department'] : NULL,
                    ];
                    $userModel->insert($change_info);
                }
            }else{
                isset($data['Avatar']) && $save_data['avatar'] = $data['Avatar'];
                isset($data['Name']) && $save_data['name'] = $data['Name'];
                isset($data['Status']) && $save_data['status'] = $data['Status'];
                isset($data['Department']) && $save_data['department_list'] = $data['Department'];
                $userinfo = $userModel->where([['userid','=',$UserId]])->findOrEmpty()->toArray();
                if($userinfo){
                    $userModel->update($save_data,['id'=>$userinfo['id']]);
                }else{ //特殊情况会到这里
                    $save_data['userid'] = $UserId;
                    $userModel->insert($save_data);
                }
            }
            Log::write('[回调]更新成员成功','info');
            Db::commit();
        }catch (\Exception $e){
            Db::rollback();
            Log::write('[回调]更新成员失败,数据已回滚,错误原因:'.$e->getMessage().'行号:'.$e->getLine(),'error');
        }
    }

    /**回调删除成员
     * @param $data
     */
    public static function delete_user($data)
    {
        $userModel = new User();
        $userinfo = $userModel->where([['userid','=',$data['UserID']]])->findOrEmpty()->toArray();
        if($userinfo){
            $userModel->update(['status'=>2],['id'=>$userinfo['id']]);
            $userModel->update(['main_department' => 9999999], ['id' => $userinfo['id']]); //直接放入离职部门,不用删除
//            $userModel::destroy(['id' => $userinfo['id']], false);
            Log::write('[回调]删除成员成功','info');
        }else{
            Log::write('[回调]删除成员不存在','notice');
        }

    }

    /**回调添加部门
     * @param $data
     */
    public static function add_department($data)
    {
        $save_data = [
            'id'=>$data['Id'],
            'name'=>$data['Name'],
            'order'=>$data['Order'],
            'parentid'=>$data['ParentId']
        ];
        $department = new Department();
        $department->save($save_data);
        Log::write('[回调]添加部门成功','info');
    }

    /**回调更新部门
     * @param $data
     */
    public function update_department($data)
    {
        $update = [
            'name' => $data['Name'],
            'parentid' => $data['ParentId'],
        ];
        $department = new Department();
        if(($department->where('id','=',$data['Id'])->count()) > 0){
            $department->update($update,['id'=>$data['Id']]);
            Log::write('[回调]更新部门成功','info');
        }else{
            $update ['id'] = $data['Id'];
            $department->save($update);
            Log::write('[回调]更新部门不存在,添加部门成功','info');
        }
    }

    /**回调删除部门
     * @param $data
     */
    public function delete_department($data)
    {
        $department = new Department();
        if(($department->where('id','=',$data['Id'])->count()) > 0){
            $department->where('id','=',$data['Id'])->delete();
            Log::write('[回调]删除部门成功','info');
        }else{
            Log::write('[回调]删除部门失败,部门不存在','notice');
        }
    }


}